<?php
/**
 * Created by PhpStorm.
 * User: yzr
 * Date: 1/25/2021
 * Time: 23:33
 */
namespace app\api\controller\wap;


use app\common\model\feature\communal\File;
use app\common\model\job\Type;
use app\common\model\users\AccountLevelLimit;
use app\common\model\users\Wallet;
use mall\utils\Tool;
use think\facade\Db;
use think\facade\Request;

class Job extends Base
{

    //为了验证地址而添加的 url 前缀
    private $urlValidatePre = 'http://a---';

    /**
     * 获取任务分类
     */
    public function category()
    {
        try{
            $typeModel = (new Type());
            $list = $typeModel->fetchListByClassification(2,Type::STATUS_ENABLE);
            $formatValue = function ($value) use (&$formatValue){
                unset($value['pid'],$value['status']);
                if(array_key_exists('sublist',$value)) {
                    $value['sublist'] = array_map($formatValue, $value['sublist']);
                }
                return $value;
            };
            $list = array_values($list);
            $list = array_map($formatValue,$list);
        }catch (\Exception $e) {
            return $this->returnAjax('系统繁忙，请稍后再试',0);
        }
        return $this->returnAjax("ok",1,$list);
    }




    /**
     * 发布任务
     */
    public function issue()
    {
        if(Request::get('upload')) {
            return $this->issueUpload();
        }

        if(Request::get('config')) {

            return $this->issueConfig();
        }

        /********** 发布信息 **********/

        try {
            // 验证提交参数
            $params = $this->issueValidateParams();

            $jobModel = (new \app\common\model\job\Job());
            // 验证客户数据
            $validateData = $jobModel->issueValidate($params);
            Db::startTrans();
            //发布数据
            $jobModel->issue($params,$validateData);
            Db::commit();
        }catch (\Exception $e) {
            Db::rollback();
            return $this->returnAjax(Tool::getErrorMessage($e),0);
        }
        // 成功返回
        return $this->returnAjax("任务发布成功",1,[]);
    }

    /**
     * 编辑任务
     * @param $id
     */
    public function edit($id){
        try {
            $jobModel = new \app\common\model\job\Job();
            if(!($details = $jobModel->findById($id)) || $details->publisher_id != \mall\basic\Users::get('id')) {
                throw new \Exception('任务不存在');
            } else if($details->status != $jobModel::STATUS_EFFECTIVE) {
                throw new \Exception('非正常状态不可编辑');
            }
            $params = $this->editValidateParams();
            Db::startTrans();
            //发布数据
            $jobModel->edit($details,$params);
            Db::commit();
        }catch (\Exception $e) {
            Db::rollback();
            return $this->returnAjax(Tool::getErrorMessage($e),0);
        }
        // 成功返回
        return $this->returnAjax("任务编辑成功",1,[]);
    }



    /**
     * 验证编辑数据
     * @return mixed|\think\response\Json
     */
    private function editValidateParams() {
        $returnErrFunc = function ($errMsg) {
            throw new \Exception($errMsg);
        };

        /****************** 验证编辑参数 **********************/
        // 可编辑参数验证
        $editFields = [
            'type_id'   => ['require|integer|>:0','请选择正确的类型'],
            'name'  => ['require|min:2|max:200','名称必须在 2 ~ 200 个字内'],
            'duration'  => ['require|float|between:1,100000','时长取值范围 1 ~ 10W'],
            'requirement'   => ['require|min:2|max:60000','详情必须在 2 ~ 6W 个字内'],
            'verify_imgs'   => ['require','请选择图片'],
            'task_link' => ['url','请填写正确的任务链接'],
            ];
        $post = Request::post();
        $params = [];
        foreach($post as $key=>$value) {
            if(array_key_exists($key,$editFields)) {
                $params[$key] = trim($value);
                if($key == 'task_link') {
                    $params[$key] = $this->urlValidatePre . $params[$key];
                }
                validate([$key=>$editFields[$key][0]],[$key=>$editFields[$key][1]])->check($params);
            }
        }
        if(array_key_exists('task_link',$params)){
            $params['task_link'] = substr($params['task_link'],strlen($this->urlValidatePre));
        }
        if(empty($params)) {
            $returnErrFunc('未做任务编辑');
        }
        /**************** END 验证编辑参数 ********************/

        foreach($params as $key=>$value) {
            switch($key) {
                case 'type_id':
                    /******** 验证类型 ********/
                    $list = (new Type())->fetchListByClassification(2,Type::STATUS_ENABLE);
                    $idList = [];
                    $getIdListFunc = function ($list) use (&$getIdListFunc,&$idList) {
                        foreach($list as $value) {
                            $idList[] = $value['id'];
                            if(array_key_exists('sublist',$value) && !empty($value['sublist'])) {
                                $getIdListFunc($value['sublist']);
                            }
                        }
                    };
                    $getIdListFunc($list);
                    if(!in_array($params['type_id'],$idList)) {
                        $returnErrFunc('类型不存在，请刷新重试');
                    }
                    /****** END 验证类型 ******/
                    break;
                case 'duration':
                    /****** 验证时长 ******/
                    $durationList = array_column(\app\common\model\job\Job::fetchDurationList(),'key');
                    if(!in_array($params['duration'],$durationList)) {
                        $returnErrFunc('时长选项不存在，请刷新重试');
                    }
                    /**** END 验证时长 ****/
                    break;
                case 'verify_imgs':
                    /**** 验证图片 ******/
                    $params['verify_imgs'] = array_unique(explode(',',$params['verify_imgs']));
                    $num = count($params['verify_imgs']);
                    if($num <1 || $num >3) {
                        $returnErrFunc('验证图片必须 1 ~ 3 张');
                    }
                    foreach($params['verify_imgs'] as $filename) {
                        if(!File::file_exists($filename,$this->getFileType())) {
                            $returnErrFunc('图片不存在，请重试');
                        }
                    }
                    /** END 验证图片 ****/
                    break;
            }
        }

        //返回数据整理结果
        return $params;
    }


    /**
     * 获取任务列表
     */
    public function fetchList()
    {

        $search = Request::get('search','');
        $where = [
            ['exp_time','>',time()],
            ['status','=',\app\common\model\job\Job::STATUS_EFFECTIVE]
        ];
        if(!empty($search)) {   // 添加搜索条件
            $where[] = ['name','like','%' . $search . '%'];
        }
        if($typeId = Request::get('category',0,'intval')) {
            $where[] = ['type_id','=',$typeId];
        }
        if($scope = Request::get('scope','','')) {
            $scopeArr = explode('~',$scope);
            if(count($scopeArr) > 1) {
                $where[] = ['price','>=',floatval($scopeArr[0])];
                $where[] = ['price','<=',floatval($scopeArr[1])];
            }
        }

        return $this->fetchListSelectAndFormatOutput($where);
    }


    /**
     * 我的发布列表
     * @return \think\response\Json
     */
    public function myFetchList() {

        $where = [
            ['publisher_id','=',\mall\basic\Users::get('id')],
        ];

        $order = ['publish_time'=>'desc'];
        $fields = ['id','name','num','accept_num','price','total_amount','exp_time','publish_time'=>'create_time','users-avatar'=>'avatar','status'];
        return $this->fetchListSelectAndFormatOutput($where,$order,$fields);
    }

    /**
     * 任务接单列表
     * @param $id
     */
    public function myAccepList($id) {
        $return = [
            'details'   => [],
            'acceptList'  => [],
            'nextPage' => [],
        ];
        try {
            // 获取任务
            if(!$details = (new \app\common\model\job\Job())->findById($id,\mall\basic\Users::get('id') )) {
                throw new \Exception('任务不存在');
            }
            $details->publisher;
            $details = $details->toArray();
            $details['publisher-avatar'] = $details['publisher']['avatar'];
            $detailsFields = ['id','name','num','accept_num','price','total_amount','publisher-avatar'=>'avatar','status'];
            foreach($detailsFields as $key=>$val) {
                if(is_integer($key)) {
                    $key = $val;
                }
                $echo = $details[$key];
                switch($val) {
                    case 'publisher-avatar':
                        $echo = Tool::url($echo,null,'avatar');
                        break;
                }
                $return['details'][$val] = $echo;
            }

            $fetchAcceptResult = (new JobAccept())->fetchListByJobId($details['id']);
            if($fetchAcceptResult['status'] != 1) {
                throw new \Exception($fetchAcceptResult['info']);
            }

            $return['acceptList'] = $fetchAcceptResult['data']['list'];
            $return['nextPage'] = $fetchAcceptResult['data']['nextPage'];
        }catch (\Exception $e) {
            return $this->returnAjax(Tool::getErrorMessage($e),0);
        }
        return $this->returnAjax("ok",1,$return);
    }


    /**
     * 获取任务详情
     * @param $id
     */
    public function details($id,$type = 'pub'){

        try {
            if(!$details = (new \app\common\model\job\Job())->findById($id)) {
                throw new \Exception('任务不存在');
            }
            $outputFields = [
                'id','name','num','accept_num','price','total_amount','exp_time','publisher-avatar'=>'avatar','publisher_id','verify_imgs','requirement','task_link','type_id'
            ];
            switch($type) {
                case 'pub': // 公开
                    //if($details['exp_time'] < time() || $details['status'] != \app\common\model\job\Job::STATUS_EFFECTIVE) {
                    if($details['exp_time'] < time() || !in_array($details['status'],[\app\common\model\job\Job::STATUS_EFFECTIVE,\app\common\model\job\Job::STATUS_PENDING_APPROVAL])) {
                        throw new \Exception('任务已过期');
                    }
                    break;
            }
            /******* 整理数据输出 ********/
            $details->requirement;
            $details->images;
            $details->publisher;
            $details = $details->toArray();
            foreach($details['publisher'] as $key=>$val) {
                $details['publisher-' . $key] = $val;
            }
            unset($details['publisher']);
            $details['requirement'] =  $details['requirement']['requirement'];
            $details['verify_imgs'] = array_map(function($filename) {
                return [
                    'thumb_url'  => $echo = Tool::url($filename,null,'job'),
                    'url'   => Tool::url($filename),
                ];
            },array_column($details['images'],'filename'));
            /***** END 整理数据输出 *******/

            /****** 格式化输出字段 ******/
            $result = [];
            foreach($outputFields as $key=>$val) {
                if(is_integer($key)) {
                    $key = $val;
                }
                $echo = $details[$key];
                switch($val) {
                    case 'exp_time':
                        $echo = date('Y-m-d H:i',$echo);
                        break;
                }
                $result[$val] = $echo;
            }
            /**** END 格式化输出字段 ****/

        }catch (\Exception $e) {
            return $this->returnAjax(Tool::getErrorMessage($e),0);
        }

        return $this->returnAjax("ok",1,$result);
    }


    /**
     * 接收任务
     */
    public function accept($id)
    {

        try {
            if(!$details = (new \app\common\model\job\Job())->findById($id)) {
                throw new \Exception('任务不存在');
            }
            /**************** 验证数据权限 ************/
            if($details['exp_time'] < time() || $details['status'] != \app\common\model\job\Job::STATUS_EFFECTIVE) {
                throw new \Exception('任务已过期');
            }
            // 验证数量
            if($details['accept_num'] >= $details['num']) {
                throw new \Exception('任务已被抢光');
            }
            // 验证自己
            if($details['publisher_id'] == \mall\basic\Users::get('id')) {
                throw new \Exception('无法接自己的任务');
            }

            // 验证接单等级
            $accountLevelLimitModel = new AccountLevelLimit();
            $accountLevelLimitDetails = $accountLevelLimitModel->findByUserId(\mall\basic\Users::get('id'));
            list($min,$max) = $accountLevelLimitModel->getAcceptPriceRange($accountLevelLimitDetails);
            if($details['price'] < $min) {
                $errMsg = '当前接单等级为：' . $accountLevelLimitDetails['accept-name'] . '，';
                $errMsg .= $max == -1?('接单价格不小于' . $min):('接单价格范围 ' . $min . ' ~ ' . $max);
                throw new \Exception($errMsg);
            }
            if($max != -1 && $details['price'] > $max) {
                return $this->returnAjax('接单等级不够，请先提升接单等级',0,[
                    'acceptLevelList'  => array_map(function($value) use($accountLevelLimitDetails){
                        return [
                            'current'   => $value['level_id'] == $accountLevelLimitDetails['accept_level']?true:false,
                            'min'   =>  0,
                            'max'   => $value['limits'] - 0,
                            'level_id'  =>  $value['level_id'],
                            'amount'    => $value['amount'] - 0,
                        ];
                    },$accountLevelLimitModel->getAcceptLevelDetails())
                ]);
            }
            /************** END 验证数据权限 **********/

            // 进行接单操作
            try{
                Db::startTrans();
                (new \app\common\model\job\Job())->accept($details->toArray(),$accountLevelLimitDetails);
                Db::commit();
            }catch (\Exception $e) {
                Db::rollback();
                throw $e;
            }

        }catch (\Exception $e) {

            //return $e->getLine().'----'.$e->getMessage();
            return $this->returnAjax(Tool::getErrorMessage($e),0);
        }

        // 成功返回
        return $this->returnAjax("任务接单成功",1,[]);
    }

    /**
     * 查询，并格式化列表输出内容
     * @param $where 查询条件
     * @param $fields 格式化输出字段
     * @return \think\response\Json
     */
    private function fetchListSelectAndFormatOutput($where,$order = null,$fields = null){
        try {
            $fields = empty($fields)?['id','name','num','accept_num','price','total_amount','exp_time','users-avatar'=>'avatar']:$fields;
            // 获取任务列表
            $list = (new \app\common\model\job\Job())->recordAllPageByDropDown($where,7,$order,['users-avatar']);
            $list['list'] = array_map(function($value) use($fields){
                $result = [];
                foreach($fields as $key=>$val) {
                    if(is_integer($key)) {
                        $key = $val;
                    }
                    $echo = $value[$key];
                    switch($key) {
                        case 'exp_time':
                        case 'publish_time':
                        //    $echo = date('Y-m-d H:i',is_string($echo)?strtotime($echo):$echo);
                            $echo = date('Y-m-d H:i',$echo);
                            break;
                        case 'users-avatar':    // 缩略图
                            $echo = Tool::url($echo,null,'avatar');
                            break;
                    }
                    $result[$val] = $echo;
                }
                return $result;
            },$list['list']);
        }catch (\Exception $e) {
            return $this->returnAjax(Tool::getErrorMessage($e),0);
        }

        // 返回列表信息
        return $this->returnAjax("ok",1,$list);
    }



    /**
     * 上传文件
     * @return \think\response\Json
     */
    private function issueUpload(){
        try{
            $resultData = File::upload($this->getFileType(),'file');
        }catch (\Exception $e) {
            return $this->returnAjax(Tool::getErrorMessage($e),0);
        }
        return $this->returnAjax("ok",1,$resultData);
    }


    /**
     * 验证发布信息
     * @return mixed|\think\response\Json
     */
    private function issueValidateParams() {
        $returnErrFunc = function ($errMsg) {
            throw new \Exception($errMsg);
        };
        $params = array_map(function($value){return trim($value);},Request::post());
        if(array_key_exists('task_link',$params)) {
            $params['task_link'] = $this->urlValidatePre .  $params['task_link'];
        }
        validate([
            'balance'   => 'require|float|>:0',
            'verify'   => 'require|length:10',
            'type_id'   =>  'require|integer|>:0',
            'name'  => 'require|min:2|max:200',
            'num'   => 'require|integer|between:1,10000',
            'price' => 'require|float|>:0',
            'total_amount'  =>  'require|float|>:0',
            'duration'  => 'require|float|between:1,100000',
            'requirement'   => 'require|min:2|max:60000',
            'verify_imgs'   => 'require',
            'task_link' => 'url'
        ],[
            'type_id'   =>  '类型不能为空',
            'name'  => '名称必须在 2 ~ 200 个字内',
            'num'   => '数量取值范围 1 ~ 1W',
            'price' => '价格必须大于 0 ',
            'total_amount'  =>  '总价必须大于 0',
            'duration'  => '时长取值范围 1 ~ 10W',
            'requirement'   => '详情必须在 2 ~ 6W 个字内',
            'verify_imgs'   => '请选择图片',
            'balance'   => '余额数据错误，请刷新重试',
            'verify'   => '验证数据错误，请刷新重试',
            'task_link' => '请填写正确的任务链接',
        ])->check($params);
        if(array_key_exists('task_link',$params)){
            $params['task_link'] = substr($params['task_link'],strlen($this->urlValidatePre));
        }

        /******** 验证类型 ********/
        $list = (new Type())->fetchListByClassification(2,Type::STATUS_ENABLE);
        $idList = [];
        $getIdListFunc = function ($list) use (&$getIdListFunc,&$idList) {
            foreach($list as $value) {
                $idList[] = $value['id'];
                if(array_key_exists('sublist',$value) && !empty($value['sublist'])) {
                    $getIdListFunc($value['sublist']);
                }
            }
        };
        $getIdListFunc($list);
        if(!in_array($params['type_id'],$idList)) {
            $returnErrFunc('类型不存在，请刷新重试');
        }
        /****** END 验证类型 ******/

        /****** 验证价格 ******/
        if(bcadd($params['price'],0,2) != $params['price']) {
            $returnErrFunc('价格小数点最多保留两位');
        }

        if(bcmul($params['price'],$params['num'],2) != $params['total_amount']) {
            $returnErrFunc('总价计算错误，请刷新重试');
        }
        if(bccomp($params['balance'],$params['total_amount'],2) == -1) {
            $returnErrFunc('发单总价不能超出账户余额');
        }
        /**** END 验证价格 ****/

        /****** 验证时长 ******/
        $durationList = array_column(\app\common\model\job\Job::fetchDurationList(),'key');
        if(!in_array($params['duration'],$durationList)) {
            $returnErrFunc('时长选项不存在，请刷新重试');
        }
        /**** END 验证时长 ****/

        /**** 验证图片 ******/
        $params['verify_imgs'] = array_unique(explode(',',$params['verify_imgs']));
        $num = count($params['verify_imgs']);
        if($num <1 || $num >3) {
            $returnErrFunc('验证图片必须 1 ~ 3 张');
        }
        foreach($params['verify_imgs'] as $filename) {
            if(!File::file_exists($filename,$this->getFileType())) {
                $returnErrFunc('图片不存在，请重试');
            }
        }
        /** END 验证图片 ****/

        //返回数据整理结果
        return $params;
    }

    /**
     * 获取配置信息
     * @return \think\response\Json
     */
    private function issueConfig() {

        try {
            $userId = \mall\basic\Users::get('id');
            /******** 获取发布等级限制 ****/
            $accountLevelimitModel = new AccountLevelLimit();
            $issueDetails = $accountLevelimitModel->findByUserId($userId);
            /****** END 获取发布等级限制 **/
            $result = [
                'balance'   => (new Wallet())->getBalanceCount($userId) ,   //余额
                'verify'    => $accountLevelimitModel->getIssueVerify($issueDetails),  //验证参数
                'issueRemainTimes'  => $accountLevelimitModel->getIssueRemainTimes($issueDetails),
                'issueLevelList'    => array_map(function($value) use($issueDetails){
                    $value['current'] = $value['level_id'] == $issueDetails['issue_level']?true:false;
                    $value['limits'] -= 0;
                    $value['amount'] -= 0;
                    return $value;
                },$accountLevelimitModel->getIssueLevelDetails()),  //等级列表
                'durationList'  => \app\common\model\job\Job::fetchDurationList(),  //时长列表

            ];
        } catch (\Exception $e) {
            return $this->returnAjax(Tool::getErrorMessage($e),0);
        }
        return $this->returnAjax("ok",1,$result);
    }

    /**
     * 获取任务价格单价区间收索列表0-40 40-400
     * @return \think\response\Json
     */
    public function priceScope()
    {
        try{
            $list = (new \app\common\model\job\Job())->fetchPriceScopeList();
        }catch (\Exception $e) {
            return $this->returnAjax('系统繁忙，请稍后再试',0);
        }
        return $this->returnAjax("ok",1,$list);
    }


    /**
     * 获取存储文件的文件类型
     * @return string
     */
    private function getFileType()
    {
        return \app\common\model\job\Job::FILE_TYPE;
    }
}
